package game;

import highscore.HighScore;
import observers.*;
import highscore.HighScoreDatabase;
import highscore.HighScoreDatabaseFactory;
import io.InputOutput;
import io.InputOutputFactory;
import java.io.*;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class Engine extends Observable {

	public static final int PLAYER_WIN = 1;
	public static final int COMPUTER_WIN = 0;
	public static final int DRAW = -1;
	public static final int UNDEFINED = 5;

	public boolean initialized;
	protected int move;
	protected int computerMove;

	private boolean undefined = false;

	public void playGame() throws IOException {
		InputOutputFactory instance = new InputOutputFactory();
		InputOutput choice = instance.newInputOutput();
		TicTacToeBoard gameBoard = new ArrayBoard();
	/*	HighScoreDatabaseFactory highScoreFactory = new HighScoreDatabaseFactory();
		HighScoreDatabase highScoreDatabase = highScoreFactory.newDatabase();
		HighScore highScoreKeeper = highScoreDatabase.retrieveHighScore(); */
		int playerScore = 0;
		int computerScore = 0;

		do {
			System.out.println("dur");
			Player computer = new AI(gameBoard);
			Player human = new User(gameBoard, choice); 
			registerObserver(new PlayerOneObserver());
			Observer playerObserver = getObservers(0);
			while (getResult(gameBoard) == UNDEFINED) {
				move = human.getMove();
				computerMove = computer.getMove();
				boolean userTurn = true;
				notifyObservers(new PlayerMoveEvent(human, "Player made a move on space number " + move));
				while (userTurn == true) {
					if(gameBoard.checkFree(move) == true) {
						gameBoard.placeMove(move, TicTacToeBoard.X);
						userTurn = false;
					} else {
						move = human.getMove();
					}
				}
				while (userTurn = false) {
					if(gameBoard.checkFree(computerMove) == true) {
						gameBoard.placeMove(computerMove, TicTacToeBoard.O);
						userTurn = true;
					} else {
						computerMove = computer.getMove();
					}
				}
				if (getResult(gameBoard) == PLAYER_WIN) {
					playerScore = playerScore + 10;
					notifyObservers(new PlayerWinLoseEvent("Player won the game with score of " + playerScore));
					System.out.println("You beat a randomized AI computer...you're REAL skilled....");
					String playerName = choice.newHighScoreName();
					System.out.println("Player score =" + playerScore);
			/*		highScoreKeeper.addScore(playerName, playerScore);
					highScoreDatabase.write(highScoreKeeper); */
					notifyObservers(new PlayerWinLoseEvent("Player saved their high score of " + playerScore + " to the database!"));
					break;
				}
				if (getResult(gameBoard) == COMPUTER_WIN) {
					computerScore = computerScore + 10;
					notifyObservers(new PlayerWinLoseEvent("Aw man, the player lost the game to the computer!"));
					System.out.println("Wow...you just got your ass handed to you by a robot...weak bro.");
					System.out.println("Computer Score = " + computerScore);
					break;
				}
				if (getResult(gameBoard) == DRAW) {
					System.out.println("IT'S A DRAW!");
					notifyObservers(new PlayerWinLoseEvent("The player and the computer came to a draw!"));
					break;
				}
				choice.showBoard(gameBoard);
			}
			gameBoard.reset();
			unregisterObserver(playerObserver);
		/*	while(choice.getResponse() != false){
				showHighScore(highScoreKeeper); 
			} */
		} while (choice.checkExit() != false);
	}

	private int getResult(TicTacToeBoard gameBoard) {
		boolean checker = false;
		while (checker == false) {
			if (gameBoard.getValue(0) == TicTacToeBoard.X
					&& gameBoard.getValue(1) == TicTacToeBoard.X
					&& gameBoard.getValue(2) == TicTacToeBoard.X) {
				checker = true;
				return PLAYER_WIN;
			}
			if (gameBoard.getValue(3) == TicTacToeBoard.X
					&& gameBoard.getValue(4) == TicTacToeBoard.X
					&& gameBoard.getValue(5) == TicTacToeBoard.X) {
				checker = true;
				return PLAYER_WIN;
			}
			if (gameBoard.getValue(6) == TicTacToeBoard.X
					&& gameBoard.getValue(7) == TicTacToeBoard.X
					&& gameBoard.getValue(8) == TicTacToeBoard.X) {
				checker = true;
				return PLAYER_WIN;
			}
			if (gameBoard.getValue(0) == TicTacToeBoard.X
					&& gameBoard.getValue(3) == TicTacToeBoard.X
					&& gameBoard.getValue(6) == TicTacToeBoard.X) {
				checker = true;
				return PLAYER_WIN;
			}
			if (gameBoard.getValue(1) == TicTacToeBoard.X
					&& gameBoard.getValue(4) == TicTacToeBoard.X
					&& gameBoard.getValue(7) == TicTacToeBoard.X) {
				checker = true;
				return PLAYER_WIN;
			}
			if (gameBoard.getValue(2) == TicTacToeBoard.X
					&& gameBoard.getValue(5) == TicTacToeBoard.X
					&& gameBoard.getValue(8) == TicTacToeBoard.X) {
				checker = true;
				return PLAYER_WIN;
			}
			if (gameBoard.getValue(0) == TicTacToeBoard.X
					&& gameBoard.getValue(4) == TicTacToeBoard.X
					&& gameBoard.getValue(8) == TicTacToeBoard.X) {
				checker = true;
				return PLAYER_WIN;
			}
			if (gameBoard.getValue(0) == TicTacToeBoard.O
					&& gameBoard.getValue(1) == TicTacToeBoard.O
					&& gameBoard.getValue(2) == TicTacToeBoard.O) {
				checker = true;
				return COMPUTER_WIN;
			}
			if (gameBoard.getValue(3) == TicTacToeBoard.O
					&& gameBoard.getValue(4) == TicTacToeBoard.O
					&& gameBoard.getValue(5) == TicTacToeBoard.O) {
				checker = true;
				return COMPUTER_WIN;
			}
			if (gameBoard.getValue(6) == TicTacToeBoard.O
					&& gameBoard.getValue(7) == TicTacToeBoard.O
					&& gameBoard.getValue(8) == TicTacToeBoard.O) {
				checker = true;
				return COMPUTER_WIN;
			}
			if (gameBoard.getValue(0) == TicTacToeBoard.O
					&& gameBoard.getValue(3) == TicTacToeBoard.O
					&& gameBoard.getValue(6) == TicTacToeBoard.O) {
				checker = true;
				return COMPUTER_WIN;
			}
			if (gameBoard.getValue(1) == TicTacToeBoard.O
					&& gameBoard.getValue(4) == TicTacToeBoard.O
					&& gameBoard.getValue(7) == TicTacToeBoard.O) {
				checker = true;
				return COMPUTER_WIN;
			}
			if (gameBoard.getValue(2) == TicTacToeBoard.O
					&& gameBoard.getValue(5) == TicTacToeBoard.O
					&& gameBoard.getValue(8) == TicTacToeBoard.O) {
				checker = true;
				return COMPUTER_WIN;
			}
			if (gameBoard.getValue(0) == TicTacToeBoard.O
					&& gameBoard.getValue(4) == TicTacToeBoard.O
					&& gameBoard.getValue(8) == TicTacToeBoard.O) {
				checker = true;
				return COMPUTER_WIN;
			}
			if (checkDraw(gameBoard) == true) {
				checker = true;
				return DRAW;
			}
			break;
		}
		checker = true;
		undefined = true;
		return UNDEFINED;
	}

	public void importantOperation(String message) throws IOException,
			FileNotFoundException {
		notifyObservers(new Event(message));
	}

	public void showHighScore(HighScore highScore) {
		Iterator<Entry<String, Integer>> entries = highScore.getMap().entrySet().iterator(); 
		while(entries.hasNext()){
			Map.Entry<String, Integer> entry = entries.next(); 
			System.out.println(entry.getKey()+ " : " + entry.getValue()); 
		}
	}
	
	private boolean checkDraw(TicTacToeBoard x) {
		for (int i = 0; i < 8; i++) {
			if (x.getValue(i) != TicTacToeBoard.EMPTY && undefined == true) {
				if (i == 8) {
					return true;
				}
			}
			break;
		}
		return false;
	}
}
